/**
 * @file
 * @brief 板级描述层：初始化
 * @author
 * + 隐星魂 (Roy Sun) <xwos@xwos.tech>
 * @copyright
 * + Copyright © 2015 xwos.tech, All Rights Reserved.
 * > Licensed under the Apache License, Version 2.0 (the "License");
 * > you may not use this file except in compliance with the License.
 * > You may obtain a copy of the License at
 * >
 * >         http://www.apache.org/licenses/LICENSE-2.0
 * >
 * > Unless required by applicable law or agreed to in writing, software
 * > distributed under the License is distributed on an "AS IS" BASIS,
 * > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * > See the License for the specific language governing permissions and
 * > limitations under the License.
 */

#include "board/std.h"
#include <xwcd/soc/arm/v7m/arch_init.h>
#include <xwcd/soc/arm/v7m/m4/s32k14x/soc_init.h>
#include <xwcd/soc/arm/v7m/armv7m_nvic.h>
#include <xwos/mm/sma.h>
#include "RTD/mif.h"

extern xwu8_t data_lma_base[];
extern xwu8_t data_vma_base[];
extern xwu8_t data_vma_end[];

extern xwu8_t bss_vma_base[];
extern xwu8_t bss_vma_end[];

/**
 * @brief 重定向数据区到内存
 */
__xwbsp_init_code
void board_relocate_data(void)
{
        xwsz_t cnt, i;
        xwu8_t * src;
        xwu8_t * dst;

        src = data_lma_base;
        dst = data_vma_base;
        if (dst != src) {
                cnt = (xwsz_t)data_vma_end - (xwsz_t)data_vma_base;
                for (i = 0; i < cnt; i++) {
                        *dst = *src;
                        dst++;
                        src++;
                }
        }

        dst = bss_vma_base;
        cnt = (xwsz_t)bss_vma_end - (xwsz_t)bss_vma_base;
        for (i = 0; i < cnt; i++) {
                *dst = 0;
                dst++;
        }
}

extern xwu8_t armv7m_ivt_lma_base[];
extern xwu8_t armv7m_ivt_vma_base[];
extern xwu8_t armv7m_ivt_vma_end[];

/**
 * @brief 重定向中断向量表到内存
 */
__xwos_init_code
void board_init_ivt(void)
{
        xwsz_t cnt, i;
        xwu8_t * src;
        xwu8_t * dst;

        src = armv7m_ivt_lma_base;
        dst = armv7m_ivt_vma_base;
        if (dst != src) {
                cnt = (xwsz_t)armv7m_ivt_vma_end - (xwsz_t)armv7m_ivt_vma_base;
                for (i = 0; i < cnt; i++) {
                        dst[i] = src[i];
                }
        }
        armv7m_scs.scb.vtor.u32 = (xwu32_t)dst;
}

__xwbsp_data struct xwmm_sma board_sa;

extern xwu8_t data_mr_origin[];
extern xwu8_t data_mr_size[];
extern xwu8_t data_mr_pos[];

/**
 * @brief 初始化内存管理
 */
__xwbsp_init_code
void board_init_mm(void)
{
        xwer_t rc;
        xwsq_t pos;

        pos = (xwsq_t)data_mr_pos - (xwsq_t)data_mr_origin;
        rc = xwmm_sma_init(&board_sa,
                           (xwptr_t)data_mr_origin,
                           (xwsz_t)data_mr_size,
                           pos,
                           "BOARD.SA");
        BOARD_BUG_ON(rc < 0);
}

extern void SystemInit(void);

__xwos_init_code
void xwos_preinit(void)
{
        arch_init();
        soc_init();
        board_relocate_data();
        board_init_ivt();
        SystemInit();
}

__xwos_init_code
void xwos_postinit(void)
{
        rtd_init();
        board_init_mm();
}
